"""配置生成命令模块"""

import argparse
from pathlib import Path
from typing import Dict, Any, Tuple, Optional, Callable
from src.core.command import Command
from src.base.registry import bera
from src.commands.parse_sql import ParseSQLCommand
from src.commands.preprocess_sql import PreprocessSQLCommand
from src.base.sql_file_utils import SQLFileUtils
from src.base.project_config import ProjectConfig
from typing import Tuple

class GenConfigCommand(Command):
    """配置生成命令"""

    SUPPORTED_FORMATS = ['common', 'java', 'typescript', 'vue3', 'springboot']

    # 定义格式描述
    FORMAT_DESC = {
        'common': '通用配置',
        'java': 'Java配置',
        'typescript': 'TypeScript配置',
        'vue3': 'Vue3配置',
        'springboot': 'SpringBoot配置'
    }

    def __init__(self):
        super().__init__()
        self.name = "gen-config"
        self.group = "代码生成"
        self.help = "生成配置文件"
        self.description = """
        根据SQL描述文件生成各种格式的配置文件。该命令会:
        1. 确保SQL描述文件存在,如不存在则自动生成
        2. 根据配置格式生成对应的配置文件
        3. 支持多种配置格式: common, java, typescript, vue3, springboot
        """

    def add_arguments(self, parser: argparse.ArgumentParser) -> None:
        # 添加通用参数
        SQLFileUtils.add_arguments(parser)

        # 添加命令特有参数
        parser.add_argument('--force', action='store_true', help='强制重新生成配置文件')

    def execute(self, args: argparse.Namespace, callback: Optional[Callable[[], None]] = None) -> None:
        """执行命令"""
        try:
            bera.logger.info("开始执行gen-config命令")

            # 先初始化项目配置
            ProjectConfig.init(args.project_dir)

            # 添加项目配置的sql-dir到搜索路径
            sql_dir = str(ProjectConfig.get_sql_dir())
            bera.logger.debug(f"添加项目配置的SQL目录到搜索路径: {sql_dir}")
            SQLFileUtils.add_search_path(sql_dir)

            # 执行callback
            if callback:
                callback()

            # 使用统一的输入模式处理
            SQLFileUtils.execute_file_processing(args, self._process_sql_file)

            bera.logger.info("gen-config命令执行完成")
        except Exception as e:
            bera.logger.error(f"gen-config命令执行失败: {str(e)}")
            if args.verbose:
                import traceback
                traceback.print_exc()
            raise

    def _process_sql_file(self, filepath: str, args: argparse.Namespace) -> None:
        """处理单个文件

        Args:
            filepath: SQL文件路径
            args: 命令行参数
        """
        try:
            # 从文件路径中提取表名
            table_name = Path(filepath).stem
            bera.logger.info(f"处理表: {table_name}")

            # 确保预处理文件存在
            bera.logger.debug("检查预处理文件")
            mark_file, sql_file = self._generate_prerequisite_files(table_name, args)

            # 读取并验证JSON文件
            sql_data = SQLFileUtils.read_and_validate_sql_json(sql_file)

            mark_data = SQLFileUtils.read_and_validate_sql_json(mark_file, validate=False)

            # 生成配置
            self._generate_configs(table_name, sql_data, mark_data, args)

        except Exception as e:
            bera.logger.error(f"处理表失败: {table_name}")
            if args.verbose:
                import traceback
                traceback.print_exc()
            SQLFileUtils.handle_file_error(e, Path(filepath), table_name)

    def _generate_prerequisite_files(self, table_name: str, args: argparse.Namespace) -> Tuple[Path, Path]:
        """生成前置依赖文件

        Args:
            table_name: 表名
            args: 命令行参数

        Returns:
            Tuple[Path, Path]: (mark.json文件路径, sql.json文件路径)
        """
        # 获取文件路径
        mark_file = SQLFileUtils.get_output_merge_dir(table_name) / "mark.json"
        sql_file = SQLFileUtils.get_output_merge_dir(table_name) / "sql.json"

        # 执行 preprocess-sql
        preprocess_cmd = PreprocessSQLCommand()
        preprocess_args = self._create_preprocess_args(table_name, args)
        preprocess_cmd.execute(preprocess_args)

        # 执行 parse-sql
        parse_cmd = ParseSQLCommand()
        parse_args = self._create_parse_args(table_name, args)
        parse_cmd.execute(parse_args)

        return mark_file, sql_file

    def _create_preprocess_args(self, table_name: str, args: argparse.Namespace) -> argparse.Namespace:
        """创建预处理命令参数"""
        return argparse.Namespace(
            filename=table_name,
            filepath=None,
            directory=None,
            verbose=args.verbose,
            format_create=False,
            format_insert=False,
            project_dir=args.project_dir
        )

    def _create_parse_args(self, table_name: str, args: argparse.Namespace) -> argparse.Namespace:
        """创建解析命令参数"""
        return argparse.Namespace(
            filename=table_name,
            filepath=None,
            directory=None,
            verbose=args.verbose,
            project_dir=args.project_dir,
            output=str(SQLFileUtils.get_output_tables_dir())
        )

    def _generate_configs(self, table_name: str, sql_data: dict, mark_data: dict, args: argparse.Namespace) -> None:
        """生成配置文件"""
        try:
            # 获取配置格式列表
            config_formats = mark_data['table'].get('config_formats', [])
            if not config_formats:
                config_formats = ['common']  # 默认生成 common.json
            elif 'common' not in config_formats:
                config_formats.insert(0, 'common')  # 确保 common.json 始终生成

            bera.logger.info(f"生成配置文件: {table_name} [{', '.join(config_formats)}]")

            # 获取并创建目录
            artifacts_config_dir = SQLFileUtils.get_output_merge_dir(table_name)
            assets_config_dir = ProjectConfig.get_config_dir() / table_name

            # 处理每个配置格式
            for fmt in config_formats:
                if fmt not in self.SUPPORTED_FORMATS:
                    raise ValueError(f"不支持的配置格式: {fmt}")

                artifacts_file = artifacts_config_dir / f"{fmt}.json"
                assets_file = assets_config_dir / f"{fmt}.json"

                # 创建生成配置的闭包函数
                def generate_config():
                    return self._generate_config(sql_data, fmt, mark_data)

                # 处理配置文件
                SQLFileUtils.process_config_file(
                    artifacts_file=artifacts_file,
                    assets_file=assets_file,
                    generate_func=generate_config,
                    force=args.force,
                    verbose=args.verbose
                )

        except Exception as e:
            bera.logger.error(f"生成配置文件失败: {str(e)}")
            raise

    def _generate_config(self, sql_data: dict, format_name: str, mark_data: dict) -> dict:
        """生成指定格式的配置"""
        # 获取表信息
        table = sql_data["table"]
        table_name = table["name"]

        # 从mark.json中获取business_name,如果没有就使用table_name
        business_name = table_name
        if mark_data and "table" in mark_data:
            mark_business_name = mark_data["table"].get("business_name")
            if mark_business_name:
                business_name = mark_business_name

        # 获取字段信息
        columns = sql_data["columns"]
        # 将字段字典转换为列表，并按字段名排序
        fields = list(columns.values())
        fields.sort(key=lambda x: x["name"])

        if format_name == "common":
            # 生成通用配置
            config = {
                "table": {
                    "description": table.get("comment", ""),
                    "label": business_name.capitalize()
                },
                "columns": {
                    field["name"]: {
                        "label": "".join(word.capitalize() for word in field["name"].split("_")),
                        "description": field["comment"],
                        "required": not field["nullable"],
                        "primary": field.get("primary_key", False),
                        "auto_increment": field.get("auto_increment", False)
                    }
                    for field in fields
                }
            }
            return config
        elif format_name == "java":
            # 生成 Java 配置
            return {
                "table": {
                    "package": "com.example.domain",
                    "className": f"{business_name.capitalize()}",
                    "imports": [
                        "java.util.Date",
                        "javax.validation.constraints.*",
                        "lombok.Data"
                    ],
                    "annotations": [
                        "@Data",
                        f'@Table(name = "{table_name}")'
                    ]
                },
                "columns": {
                    field["name"]: {
                        "fieldName": field["name"],
                        "type": self._map_type_to_java(field["type"]["name"]),
                        "annotations": [
                            "@Id" if field.get("primary_key") else None,
                            "@GeneratedValue(strategy = GenerationType.IDENTITY)" if field.get("auto_increment") else None,
                            "@NotNull" if not field["nullable"] else None
                        ]
                    }
                    for field in fields
                }
            }
        elif format_name == "typescript":
            # 生成 TypeScript 配置
            return {
                "table": {
                    "interfaceName": f"{business_name.capitalize()}",
                    "imports": [
                        "import { IsNotEmpty, IsEnum } from 'class-validator'",
                        "import { Gender } from '@/enums'"
                    ],
                    "decorators": [
                        "@ObjectType()"
                    ]
                },
                "columns": {
                    field["name"]: {
                        "fieldName": field["name"],
                        "type": self._map_type_to_typescript(field["type"]["name"]),
                        "required": not field["nullable"],
                        "decorators": [
                            "@Field()" if not field.get("primary_key") else "@Field(() => ID)",
                            "@IsNotEmpty()" if not field["nullable"] else None
                        ],
                        "validation": {
                            "maxLength": field["type"].get("length") if field["type"]["name"].upper() in ["VARCHAR", "CHAR"] else None
                        }
                    }
                    for field in fields
                }
            }
        elif format_name == "vue3":
            # 生成 Vue3 配置
            return {
                "table": {
                    "listComponent": {
                        "pageSize": 10,
                        "showPagination": True,
                        "showSelection": True,
                        "showRefresh": True
                    },
                    "formComponent": {
                        "labelWidth": "100px",
                        "labelPosition": "right",
                        "showReset": True
                    }
                },
                "columns": {
                    field["name"]: {
                        "placeholder" : "请输入" + field["name"],
                        "list": {
                            "show": True,
                            "width": 120,
                            "sortable": True,
                            "formatter": "dateFormatter" if field["type"]["name"].upper() in ["DATE", "DATETIME", "TIMESTAMP"] else None
                        },
                        "form": {
                            "show": not field.get("auto_increment", False),
                            "type": self._get_vue_form_type(field["type"]["name"]),
                            "required": not field["nullable"],
                            "options": [{"label": v, "value": k} for k, v in field.get("enum_options", {}).items()] if field.get("enum_options") else None
                        }
                    }
                    for field in fields
                }
            }
        elif format_name == "springboot":
            # 生成 SpringBoot 配置
            return {
                "table": {
                    "controller": {
                        "package": "com.example.controller",
                        "className": f"{business_name.capitalize()}Controller",
                        "baseUrl": f"/api/{business_name}s",
                        "imports": [
                            "org.springframework.web.bind.annotation.*",
                            "org.springframework.validation.annotation.Validated"
                        ]
                    },
                    "service": {
                        "package": "com.example.service",
                        "className": f"{business_name.capitalize()}Service",
                        "implClassName": f"{business_name.capitalize()}ServiceImpl"
                    },
                    "repository": {
                        "package": "com.example.repository",
                        "className": f"{business_name.capitalize()}Repository",
                        "extends": f"JpaRepository<{business_name.capitalize()}, Long>"
                    }
                },
                "columns": {
                    field["name"]: {
                        "queryable": not field.get("auto_increment", False),
                        "queryType": self._get_spring_query_type(field["type"]["name"]),
                        "updatable": not field.get("auto_increment", False),
                        "insertable": not field.get("auto_increment", False),
                        "enumType": "INTEGER" if field.get("enum_options") else None,
                        "dateFormat": "yyyy-MM-dd" if field["type"]["name"].upper() in ["DATE", "DATETIME", "TIMESTAMP"] else None
                    }
                    for field in fields
                }
            }
        else:
            raise ValueError(f"不支持的配置格式: {format_name}")

    def _map_type_to_java(self, sql_type: str) -> str:
        """将 SQL 类型映射为 Java 类型"""
        type_map = {
            "BIGINT": "Long",
            "INT": "Integer",
            "TINYINT": "Integer",
            "VARCHAR": "String",
            "CHAR": "String",
            "TEXT": "String",
            "DECIMAL": "BigDecimal",
            "DATE": "Date",
            "DATETIME": "Date",
            "TIMESTAMP": "Date"
        }
        return type_map.get(sql_type.upper(), "String")

    def _map_type_to_typescript(self, sql_type: str) -> str:
        """将 SQL 类型映射为 TypeScript 类型"""
        type_map = {
            "BIGINT": "number",
            "INT": "number",
            "TINYINT": "number",
            "VARCHAR": "string",
            "CHAR": "string",
            "TEXT": "string",
            "DECIMAL": "number",
            "DATE": "Date",
            "DATETIME": "Date",
            "TIMESTAMP": "Date"
        }
        return type_map.get(sql_type.upper(), "string")

    def _get_vue_form_type(self, sql_type: str) -> str:
        """获取Vue表单组件类型"""
        type_map = {
            "BIGINT": "number",
            "INT": "number",
            "TINYINT": "select",
            "VARCHAR": "input",
            "CHAR": "input",
            "TEXT": "textarea",
            "DATE": "date",
            "DATETIME": "datetime",
            "TIMESTAMP": "datetime"
        }
        return type_map.get(sql_type.upper(), "input")

    def _get_spring_query_type(self, sql_type: str) -> str:
        """获取Spring查询类型"""
        type_map = {
            "VARCHAR": "LIKE",
            "CHAR": "LIKE",
            "TEXT": "LIKE",
            "DATE": "BETWEEN",
            "DATETIME": "BETWEEN",
            "TIMESTAMP": "BETWEEN"
        }
        return type_map.get(sql_type.upper(), "EQ")